Make _gdk_window_process_updates_recurse reentrancy safe
authorAlexander Larsson <alexl@redhat.com>
Thu, 13 Aug 2009 15:00:00 +0000 (17:00 +0200)
committerAlexander Larsson <alexl@redhat.com>
Thu, 13 Aug 2009 15:00:00 +0000 (17:00 +0200)
Apps may change the window hierarchy while recursing over it by
destroying windows from the expose event handler. We need to copy
the children list and ref all the children while recursing.

This fixes some crashers in gedit (bug #589367, bug #591434)

gdk/gdkwindow.c

index ba4ad63a3bc9cfef6856253160ac692560100799..e9c5512a21dbfa8b7fe66a6a219cd2d2ef1047e9 100644 (file)
@@ -4751,17 +4751,21 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
   GdkWindowObject *child;
   GdkRegion *child_region;
   GdkRectangle r;
-  GList *l;
+  GList *l, *children;
 
   if (gdk_region_empty (expose_region))
     return;
 
+  /* Make this reentrancy safe for expose handlers freeing windows */
+  children = g_list_copy (private->children);
+  g_list_foreach (children, g_object_ref, NULL);
+
   /* Iterate over children, starting at topmost */
-  for (l = private->children; l != NULL; l = l->next)
+  for (l = children; l != NULL; l = l->next)
     {
       child = l->data;
 
-      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+      if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
        continue;
 
       /* Ignore offscreen children, as they don't draw in their parent and
@@ -4799,6 +4803,9 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
       gdk_region_destroy (child_region);
     }
 
+  g_list_foreach (children, g_object_unref, NULL);
+  g_list_free (children);
+
   if (!gdk_region_empty (expose_region))
     {
       if (private->event_mask & GDK_EXPOSURE_MASK)